// Copyright (C) 2008 Taylor L. Riche <riche@cs.utexas.edu>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

/**
 * 
 */
package appcomp.pathfinder;

import core.Entity;
import appcomp.entities.*;
import java.util.LinkedList;

/**
 * @author riche
 *
 */
public class Path {
	
	private LinkedList<Connector> core;
	
	public Path() {
		core = new LinkedList<Connector>();
	}
	
	public Path(Path newPath) {
		core = new LinkedList<Connector>();
		core.addAll(newPath.core);
	}
	
	@Override 
	public String toString() {
		String retVal = "";
		for (Connector c : core) {
			retVal += c.getInName().getLeft() + "." + c.getInName().getRight() + "->" + 
			c.getOutName().getLeft() + "." + c.getOutName().getRight() + "::";
		}
		return retVal += "X";
	}
	
	/**
	 * 
	 * @param c The Connector to be added to the path
	 */
	public void addHop(Connector c) {
		core.add(c);
	}

	/**
	 * 
	 * @return The length of the path in Operators
	 */
	public int getLength() {
		int retval = 0;
		if(core.size() != 0) {
			retval = core.size() + 1;
		}
		return retval;	
	}
	
	/**
	 * 
	 * @param guarantee The end-to-end delay guarantee of the application
	 * @return The amount of time that a request can spend in queues and still meet it's delay guarantee
	 */
	public double getSlack(double guarantee) {
		double totalDelay = 0;
		for (Connector c : core) {
			totalDelay += c.getOut().getDelay(c.getOutName().getRight());
		}
		double slack = guarantee - totalDelay;
		if(slack < 0) {
			System.err.println("Guarantee not achievable.");
			System.err.println("Bad path: " + this.toString());
			System.exit(1);
		}
		return slack;
	}
	
	public void distributeSlack(double slack) {
		double perOpSlack = slack / this.getLength();
		for (Connector c : core) {
			if(!c.getOut().doesGenerate()) {
				c.getOut().setSlack(perOpSlack, c.getOutName().getRight());
			}
		}
	}
}
